//	World.java --- 

package fr.upmc.dtgui.example;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.BlockingQueue;

import javax.swing.SwingUtilities;
import fr.upmc.dtgui.gui.TeleoperationGUI;
import fr.upmc.dtgui.robot.InstrumentedRobot;
import fr.upmc.dtgui.robot.Robot;
import fr.upmc.dtgui.tests.AnotherLittleRobot;
import fr.upmc.dtgui.tests.EmptyRobot;
import fr.upmc.dtgui.tests.LittleRobot;
import fr.upmc.dtgui.example.robot.ExampleGUI;
//import fr.upmc.dtgui.tests.AnotherLittleRobot;

/**
 * The class <code>World</code> simulates a space within which robots move and
 * can be controlled by teleoperation station when they enter their control
 * area.
 *
 * <p><strong>Description</strong></p>
 * 
 * <code>World</code> is defined as a 2D plane with upper left corner
 * coordinates (0,0) and lower right coordinates (MAX_X, MAX_Y).  Robots can
 * move around this world, and teleoperation stations are put at different
 * positions.  The world is a thread that repeatedly looks at the current
 * positions of the different robots and when a robot enters the visibility
 * rectangle of a station, it is connected to that station.  Similarly, when
 * a robot is in the visibility of a station and enters its circle of control,
 * then the robot is made controllable buy this station.
 * 
 * <p><strong>Invariant</strong></p>
 * 
 * <pre>
 * invariant	true
 * </pre>
 * 
 * <p>Created on : 2011-10-10</p>
 * 
 * @author	<a href="mailto:Jacques.Malenfant@lip6.fr">Jacques Malenfant</a>
 * @version	$Name$ -- $Revision$ -- $Date$
 */
public class			World		extends Thread {

	public static int				MAX_X ;
	public static int				MAX_Y ;

	protected TeleoperationGUI[]	teleoperationStations ;
	protected Robot[]	robots ;

	public				World() {
		this.robots = new Robot[2] ;
		this.teleoperationStations = new TeleoperationGUI[2] ;
//		this.robots[0] =
//			new AnotherLittleRobot("No 5", 2000.0, 950.0, 45.0,20.0) ;
		this.robots[1] =
			new AnotherLittleRobot("No 1", 2850.0, 950.0, 135.0,20.0) ;
		this.robots[0] =
				new LittleRobot("No 5", 2000.0, 950.0, 45.0) ;
//			this.robots[1] =
//				new LittleRobot("No 1", 2850.0, 950.0, 135.0) ;
//		this.robots[0] =
//				new EmptyRobot("No 5", 2000.0, 950.0, 45.0) ;
//			this.robots[1] =
//				new EmptyRobot("No 1", 2850.0, 950.0, 135.0) ;
		this.teleoperationStations[0] =
			new ExampleGUI("1", 2500, 1500, 500, 500, 400, 1000, 1000) ;
		this.teleoperationStations[1] =
			new ExampleGUI("2", 3500, 1500, 500, 500, 400, 1000, 1000) ;
		final TeleoperationGUI[] ts = this.teleoperationStations ;
		try {
			SwingUtilities.invokeAndWait(
					new Runnable() {
						public void run() {
							for (int i = 0 ; i < ts.length ; i++) {
								ts[i].setVisible(true) ;
							}
						}
					}) ;
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	public void			start() {
		
		super.start() ;
		for (int i = 0 ; i < this.teleoperationStations.length ; i++) {
			this.teleoperationStations[i].start() ;
		}
		for (int i = 0 ; i < this.robots.length ; i++) {
			try {
				this.robots[i].getClass().getMethod("start", new Class [] {}).invoke(this.robots[i],new Object [] {});
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void			run() {
		while (true) {
			for (int i = 0 ; i < this.robots.length ; i++) {
				try {
					Double dxRobot = (Double) this.robots[i].getClass().getMethod("getX", new Class [] {}).invoke(this.robots[i],new Object [] {}) ;
					Double dyRobot = (Double) this.robots[i].getClass().getMethod("getY", new Class [] {}).invoke(this.robots[i],new Object [] {}) ;
					int xRobot = dxRobot.intValue();
					int yRobot = dyRobot.intValue();
				
					for (int j = 0 ; j < this.teleoperationStations.length ; j++) {
						int xStation =
							this.teleoperationStations[j].getAbsoluteX() ;
						int yStation =
							this.teleoperationStations[j].getAbsoluteY() ;
						int sizeXdiv2 =
							this.teleoperationStations[j].getSizeX() / 2 ;
						int sizeYdiv2 =
							this.teleoperationStations[j].getSizeY() / 2 ;
						int controlRadius =
							this.teleoperationStations[j].getControlRadius() ;
						final Robot lr = this.robots[i] ;
						final TeleoperationGUI tgui =
							this.teleoperationStations[j] ;
						
						
						/*String chaine =
								xRobot + "(xRobot) >= ("+xStation+"(xStation) - "+sizeXdiv2+"(sizeXdiv2))";
						chaine += " && ";
						chaine += xRobot + " (xRobot) <= (" + xStation + "(xStation) + " + sizeXdiv2 + "(sizeXdiv2))";
						chaine += " && ";
						chaine += yRobot + "(yRobot) >= ("+yStation+"(yStation) - "+sizeYdiv2+"(sizeYdiv2))";
						chaine += " && ";
						chaine += yRobot + " (yRobot) <= (" + yStation + "(yStation) + " + sizeYdiv2 + "(sizeYdiv2))";
						
						System.out.println(chaine);*/
						
						if (xRobot >= (xStation - sizeXdiv2) &&
											xRobot <= (xStation + sizeXdiv2) &&
							yRobot >= (yStation - sizeYdiv2) &&
											yRobot <= (yStation + sizeYdiv2)) {
							try {
								SwingUtilities.invokeAndWait(
									new Runnable() {
										public void run() {
											tgui.detectRobot((InstrumentedRobot) lr) ;
										}
									}) ;
							} catch (InterruptedException e) {
								e.printStackTrace();
							} catch (InvocationTargetException e) {
								e.printStackTrace();
							}
						} else {
							try {
								SwingUtilities.invokeAndWait(
									new Runnable() {
										public void run() {
											tgui.undetectRobot((InstrumentedRobot) lr) ;
										}
									}) ;
							} catch (InterruptedException e) {
								e.printStackTrace();
							} catch (InvocationTargetException e) {
								e.printStackTrace();
							}
						}
						int x = xRobot - xStation ;
						int y = yRobot - yStation ;
						//System.out.println(x*x + "         "+y*y);
						//System.out.println(x*x + y*y);
						//System.out.println(controlRadius);
						//System.out.println(controlRadius*controlRadius);
						if (x * x + y * y <= controlRadius * controlRadius) {
							try {
								SwingUtilities.invokeAndWait(
									new Runnable() {
										public void run() {
											tgui.makeControllable((InstrumentedRobot) lr) ;
										}
									}) ;
							} catch (InterruptedException e) {
								e.printStackTrace();
							} catch (InvocationTargetException e) {
								e.printStackTrace();
							}
						} else {
							try {
								SwingUtilities.invokeAndWait(
									new Runnable() {
										public void run() {
											tgui.makeUncontrollable((InstrumentedRobot) lr) ;
										}
									}) ;
							} catch (InterruptedException e) {
								e.printStackTrace();
							} catch (InvocationTargetException e) {
								e.printStackTrace();
							}
						}
					}
				}
				catch(Exception e) {
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(1000) ;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
	

// $Id$